package net.media.datafw.transport.transporters;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import net.media.datafw.transport.TransportException;
import net.media.datafw.transport.Transporter;
import net.media.datafw.transport.model.TransportField;
import net.media.datafw.transport.model.Transportable;
import net.media.datafw.transport.utils.TransporterUtil;

import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JSONTransporter extends Transporter {
	Logger logger = LoggerFactory.getLogger(getClass());
	@Override
	protected void writeTransportable(Transportable data, Object serilizedData) throws TransportException {
		try {
			JSONObject transportableObject = new JSONObject();
			serializeTransportable(data, transportableObject);
			((JSONObject) serilizedData).put(readClassName(data.getClass()), transportableObject);
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void writeTransportableArray(Transportable[] data, Object serilizedData) throws TransportException {
		try {
			if (data != null) {
				for (int i = 0; i < data.length; i++) {
					JSONObject serilizedJSONData = new JSONObject();
					writeTransportable(data[i], serilizedJSONData);
					((JSONArray) serilizedData).put(serilizedJSONData);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeTransportable(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				Transportable[] transportableArray = (Transportable[]) objectData;
				JSONArray transportableJSONArray = new JSONArray();
				for (int i = 0; i < transportableArray.length; i++) {
					Class<?> clazz = objectData.getClass();
					if (clazz.isArray()) {
						clazz = clazz.getComponentType();
					}

					JSONObject serializedTransportable = new JSONObject();
					JSONObject transportableObject = new JSONObject();
					serializeTransportable((Transportable) transportableArray[i], transportableObject);
					serializedTransportable.put(readClassName(clazz), transportableObject);
					transportableJSONArray.put(serializedTransportable);
				}
				((JSONObject) serializedData).put(field.getName(), transportableJSONArray);
			} else {
				JSONObject serializedTransportable = new JSONObject();
				JSONObject transportableObject = new JSONObject();
				serializeTransportable((Transportable) objectData, transportableObject);
				serializedTransportable.put(readClassName(objectData.getClass()), transportableObject);
				((JSONObject) serializedData).put(field.getName(), serializedTransportable);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected Object initialiseTrasportableArray() throws TransportException {
		return new JSONArray();
	}

	@Override
	protected Object initialiseTrasportable() throws TransportException {
		return new JSONObject();
	}

	@Override
	protected void serializeBoolean(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				boolean[] data;
				if (field.isPrimitive()) {
					data = (boolean[]) objectData;
				} else {
					Boolean[] dataArr = (Boolean[]) objectData;
					data = TransporterUtil.converBooleanArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				boolean data = ((Boolean) objectData).booleanValue();
				((JSONObject) serializedData).put(field.getName(), data);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeByte(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				byte[] data;
				if (field.isPrimitive()) {
					data = (byte[]) objectData;
				} else {
					Byte[] dataArr = (Byte[]) objectData;
					data = TransporterUtil.converByteArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				byte data = ((Byte) objectData).byteValue();
				((JSONObject) serializedData).put(field.getName(), data);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeCharacter(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				char[] data;
				if (field.isPrimitive()) {
					data = (char[]) objectData;
				} else {
					Character[] dataArr = (Character[]) objectData;
					data = TransporterUtil.converCharacterArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(String.valueOf(data[dataIdx]));
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				char data = ((Character) objectData).charValue();
				((JSONObject) serializedData).put(field.getName(), String.valueOf(data));
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeShort(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				short[] data;
				if (field.isPrimitive()) {
					data = (short[]) objectData;
				} else {
					Short[] dataArr = (Short[]) objectData;
					data = TransporterUtil.converShortArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				short data = ((Short) objectData).shortValue();
				((JSONObject) serializedData).put(field.getName(), data);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeInteger(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				int[] data;
				if (field.isPrimitive()) {
					data = (int[]) objectData;
				} else {
					Integer[] dataArr = (Integer[]) objectData;
					data = TransporterUtil.converIntegerArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				int data = ((Integer) objectData).intValue();
				((JSONObject) serializedData).put(field.getName(), data);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeLong(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				long[] data;
				if (field.isPrimitive()) {
					data = (long[]) objectData;
				} else {
					Long[] dataArr = (Long[]) objectData;
					data = TransporterUtil.converLongArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				long data = ((Long) objectData).longValue();
				((JSONObject) serializedData).put(field.getName(), data);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeFloat(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				float[] data;
				if (field.isPrimitive()) {
					data = (float[]) objectData;
				} else {
					Float[] dataArr = (Float[]) objectData;
					data = TransporterUtil.converFloatArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				float data = ((Float) objectData).floatValue();
				((JSONObject) serializedData).put(field.getName(), data);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeDouble(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				double[] data;
				if (field.isPrimitive()) {
					data = (double[]) objectData;
				} else {
					Double[] dataArr = (Double[]) objectData;
					data = TransporterUtil.converDoubleArray(dataArr);
				}

				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				double data = ((Double) objectData).doubleValue();
				((JSONObject) serializedData).put(field.getName(), data);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeString(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				String[] data = (String[]) objectData;
				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx]);
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				((JSONObject) serializedData).put(field.getName(), objectData);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeDate(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				Date[] data = (Date[]) objectData;
				JSONArray booleanArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					booleanArray.put(data[dataIdx].toString());
				}
				((JSONObject) serializedData).put(field.getName(), booleanArray);
			} else {
				((JSONObject) serializedData).put(field.getName(), objectData.toString());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}

	}

	@SuppressWarnings("unchecked")
	@Override
	protected void serializeArrayList(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				ArrayList<Object>[] data = (ArrayList<Object>[]) objectData;
				JSONArray serializedDataArrayObject = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					JSONArray serializedDataArray = new JSONArray();
					processArrayList(field, data[dataIdx], field.getComponentValueType(), serializedDataArray);
					serializedDataArrayObject.put(serializedDataArray);
				}
				((JSONObject) serializedData).put(field.getName(), serializedDataArrayObject);
			} else {
				ArrayList<Object> data = (ArrayList<Object>) objectData;
				JSONArray serializedDataArray = new JSONArray();
				processArrayList(field, data, field.getComponentValueType(), serializedDataArray);
				((JSONObject) serializedData).put(field.getName(), serializedDataArray);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void processArrayList(TransportField field, ArrayList<Object> data, Type genericValueClass, Object serializedData) throws TransportException {
		try {
			if ((Boolean.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Boolean) data.get(arrarIdx)).booleanValue());
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Byte) data.get(arrarIdx)).byteValue());
				}
			} else if ((Character.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Character) data.get(arrarIdx)).charValue());
				}
			} else if ((Short.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Short) data.get(arrarIdx)).shortValue());
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Integer) data.get(arrarIdx)).intValue());
				}
			} else if ((Long.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Long) data.get(arrarIdx)).longValue());
				}
			} else if ((Float.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Float) data.get(arrarIdx)).floatValue());
				}
			} else if ((Double.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put(((Double) data.get(arrarIdx)).doubleValue());
				}
			} else if ((String.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					((JSONArray) serializedData).put((String) data.get(arrarIdx));
				}
			} else if (isTransportable(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					JSONObject serilizedJSONData = new JSONObject();
					writeTransportable((Transportable) data.get(arrarIdx), serilizedJSONData);
					((JSONArray) serializedData).put(serilizedJSONData);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void serializeHashMap(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			if (field.isArray()) {
				HashMap<Object, Object>[] data = (HashMap<Object, Object>[]) objectData;
				JSONArray serializedDataArray = new JSONArray();
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					JSONObject serializedDataObject = new JSONObject();
					processHashMap(field, data[dataIdx], field.getComponentValueType(), serializedDataObject);
					serializedDataArray.put(serializedDataObject);
				}
				((JSONObject) serializedData).put(field.getName(), serializedDataArray);
			} else {
				HashMap<Object, Object> data = (HashMap<Object, Object>) objectData;
				JSONObject serializedDataObject = new JSONObject();
				processHashMap(field, data, field.getComponentValueType(), serializedDataObject);
				((JSONObject) serializedData).put(field.getName(), serializedDataObject);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void processHashMap(TransportField field, HashMap<Object, Object> data, Type genericValueClass, Object serializedData) throws TransportException {

		try {
			Iterator<?> keyIterator = data.keySet().iterator();

			if ((Boolean.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Boolean) data.get(key)).booleanValue());
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Byte) data.get(key)).byteValue());
				}
			} else if ((Character.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Character) data.get(key)).charValue());
				}
			} else if ((Short.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Short) data.get(key)).shortValue());
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Integer) data.get(key)).intValue());
				}
			} else if ((Long.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Long) data.get(key)).longValue());
				}
			} else if ((Float.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Float) data.get(key)).floatValue());
				}
			} else if ((Double.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, ((Double) data.get(key)).doubleValue());
				}
			} else if ((String.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					((JSONObject) serializedData).put(key, (String) data.get(key));
				}
			} else if (isTransportable(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					JSONObject serilizedJSONData = new JSONObject();
					writeTransportable((Transportable) data.get(key), serilizedJSONData);
					((JSONObject) serializedData).put(key, serilizedJSONData);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void onSerializeField(TransportField field, Object serializedData) throws TransportException {
	}

	@Override
	protected void afterSerializeField(ArrayList<TransportField> fields, Object serializedData) throws TransportException {
	}

	@Override
	protected Object parseData(byte[] data) throws TransportException {
		String dataString = new String(data);

		try {
			return new JSONArray(dataString);
		} catch (Exception e) {
			try {
				return new JSONObject(dataString);
			} catch (Exception e1) {
				throw new TransportException(e1);
			}
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected Class<?> readClass(Object serializedData) throws TransportException {
		Class<?> clazz = null;
		Iterator<String> keys = ((JSONObject) serializedData).keys();
		if (keys.hasNext()) {
			String className = keys.next();
			clazz = classNames.get(className);
		}
		return clazz;
	}

	@Override
	protected Object getTransportable(Object serializedData) {
		return serializedData;
	}

	@Override
	protected boolean isTransportableArray(Object serializedData) {
		return (serializedData instanceof JSONArray);
	}

	@Override
	protected Object readTransportableArray(Object serializedData) throws TransportException {
		Object[] transpotableArray = null;
		try {
			JSONArray transportableArray = (JSONArray) serializedData;
			if (transportableArray != null && transportableArray.length() > 0) {
				transpotableArray = new Object[transportableArray.length()];

				for (int arrayIdx = 0; arrayIdx < transportableArray.length(); arrayIdx++) {
					JSONObject serializedObjectData = (JSONObject) transportableArray.get(arrayIdx);
					transpotableArray[arrayIdx] = readTransportable(serializedObjectData);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
		return transpotableArray;
	}

	@Override
	protected Object readTransportable(Object serializedData) throws TransportException {
		Object transpotableObject = null;
		try {
			Class<?> clazz = readClass(serializedData);
			transpotableObject = clazz.newInstance();
			JSONObject transportableObject = (JSONObject) ((JSONObject) serializedData).get(readClassName(clazz));
			if (transportableObject != null) {
				ArrayList<TransportField> fields = classFields.get(clazz);
				if (fields != null) {
					for (int fieldIdx = 0; fieldIdx < fields.size(); fieldIdx++) {
						TransportField field = fields.get(fieldIdx);
						String name = field.getName();
						if (transportableObject.has(name)) {
							deserializeField(field, transportableObject.get(name), transpotableObject);
						}
					}
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
		return transpotableObject;
	}

	@Override
	protected void deserializedTransportable(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				JSONArray transportableJSONArray = (JSONArray) objectData;
				Transportable[] transportableArray = new Transportable[transportableJSONArray.length()];
				for (int i = 0; i < transportableJSONArray.length(); i++) {
					transportableArray[i] = (Transportable) readTransportable(transportableJSONArray.get(i));
				}
				field.setValue(deserializedObject, transportableArray);
			} else {
				Transportable obj = (Transportable) readTransportable(objectData);
				field.setValue(deserializedObject, obj);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeBoolean(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Boolean[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Boolean[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = jsonArray.getBoolean(dataIdx);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converBooleanArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, (Boolean) objectData);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeByte(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Byte[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Byte[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = (byte) jsonArray.getInt(dataIdx);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converByteArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, ((Integer) objectData).byteValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeCharacter(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Character[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Character[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = (Character) ((String) jsonArray.get(dataIdx)).charAt(0);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converCharacterArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, ((String) objectData).charAt(0));
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeShort(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Short[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Short[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = (short) jsonArray.getInt(dataIdx);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converShortArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, ((Integer) objectData).shortValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeInteger(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Integer[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Integer[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = jsonArray.getInt(dataIdx);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converIntegerArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, (Integer) objectData);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeLong(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Long[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Long[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = jsonArray.getLong(dataIdx);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converLongArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, Long.valueOf(objectData.toString()));
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeFloat(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Float[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Float[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = (float) jsonArray.getDouble(dataIdx);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converFloatArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, Double.valueOf(objectData.toString()).floatValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeDouble(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Double[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Double[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = jsonArray.getDouble(dataIdx);
					}
				}

				if (((Class<?>) field.getType()).getComponentType().isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converDoubleArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, Double.valueOf(objectData.toString()));
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeString(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				String[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new String[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = (String) jsonArray.get(dataIdx);
					}
				}

				field.setValue(deserializedObject, fieldValue);
			} else {
				field.setValue(deserializedObject, objectData);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeDate(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			if (field.isArray()) {
				Date[] fieldValue = null;
				JSONArray jsonArray = (JSONArray) objectData;
				if (jsonArray != null && jsonArray.length() > 0) {
					fieldValue = new Date[jsonArray.length()];

					for (int dataIdx = 0; dataIdx < jsonArray.length(); dataIdx++) {
						fieldValue[dataIdx] = simpleDateFormat.parse((String) jsonArray.get(dataIdx));
					}
				}

				field.setValue(deserializedObject, fieldValue);
			} else {
				field.setValue(deserializedObject, simpleDateFormat.parse(objectData.toString()));
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}

	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	protected void deserializeArrayList(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			Class<?> genericValueClass = (Class<?>) field.getComponentValueType();

			if (field.isArray()) {
				JSONArray serializedDataArray = (JSONArray) objectData;
				ArrayList[] deserializedDataArray = new ArrayList[serializedDataArray.length()];
				for (int dataIdx = 0; dataIdx < serializedDataArray.length(); dataIdx++) {
					ArrayList<Object> deserializedDataObject = (ArrayList<Object>) ((Class<?>) field.getRawType()).newInstance();
					readArrayList(field, (JSONArray) serializedDataArray.get(dataIdx), genericValueClass, deserializedDataObject);
					deserializedDataArray[dataIdx] = deserializedDataObject;
				}
				field.setValue(deserializedObject, deserializedDataArray);
			} else {
				ArrayList<Object> deserializedDataObject = (ArrayList<Object>) ((Class<?>) field.getRawType()).newInstance();
				readArrayList(field, (JSONArray) objectData, genericValueClass, deserializedDataObject);
				field.setValue(deserializedObject, deserializedDataObject);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void readArrayList(TransportField field, Object valueArray, Class<?> genericValueClass, Object deserializedDataObject) throws TransportException {
		try {
			JSONArray value = (JSONArray) valueArray;

			if ((Boolean.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Boolean>) deserializedDataObject).add(value.getBoolean(arrarIdx));
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Byte>) deserializedDataObject).add((byte) value.getInt(arrarIdx));
				}
			} else if ((Character.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Character>) deserializedDataObject).add((Character) value.get(arrarIdx));
				}
			} else if ((Short.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Short>) deserializedDataObject).add((short) value.getInt(arrarIdx));
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Integer>) deserializedDataObject).add(value.getInt(arrarIdx));
				}
			} else if ((Long.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Long>) deserializedDataObject).add(value.getLong(arrarIdx));
				}
			} else if ((Float.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Float>) deserializedDataObject).add((float) value.getDouble(arrarIdx));
				}
			} else if ((Double.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Double>) deserializedDataObject).add(value.getDouble(arrarIdx));
				}
			} else if ((String.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<String>) deserializedDataObject).add((String) value.get(arrarIdx));
				}
			} else if (isTransportable(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < value.length(); arrarIdx++) {
					((ArrayList<Transportable>) deserializedDataObject).add((Transportable) readTransportable(value.get(arrarIdx)));
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	protected void deserializeHashMap(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			Class<?> genericValueClass = (Class<?>) field.getComponentValueType();

			if (field.isArray()) {
				JSONArray serializedDataArray = (JSONArray) objectData;
				HashMap[] deserializedDataArray = new HashMap[serializedDataArray.length()];
				for (int dataIdx = 0; dataIdx < serializedDataArray.length(); dataIdx++) {
					HashMap<String, Object> deserializedDataObject = (HashMap<String, Object>) ((Class<?>) field.getRawType()).newInstance();
					readHashMap(field, (JSONObject) serializedDataArray.get(dataIdx), genericValueClass, deserializedDataObject);
					deserializedDataArray[dataIdx] = deserializedDataObject;
				}
				field.setValue(deserializedObject, deserializedDataArray);
			} else {
				HashMap<String, Object> deserializedDataObject = (HashMap<String, Object>) ((Class<?>) field.getRawType()).newInstance();
				readHashMap(field, (JSONObject) objectData, genericValueClass, deserializedDataObject);
				field.setValue(deserializedObject, deserializedDataObject);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void readHashMap(TransportField field, Object valueObject, Class<?> genericValueClass, Object deserializedDataObject) throws TransportException {
		try {
			JSONObject value = (JSONObject) valueObject;

			Iterator<String> keys = value.keys();
			if ((Boolean.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Boolean>) deserializedDataObject).put(key, (Boolean) value.get(key));
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Byte>) deserializedDataObject).put(key, (Byte) value.get(key));
				}
			} else if ((Character.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Character>) deserializedDataObject).put(key, (Character) value.get(key));
				}
			} else if ((Short.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Short>) deserializedDataObject).put(key, (Short) value.get(key));
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Integer>) deserializedDataObject).put(key, (Integer) value.get(key));
				}
			} else if ((Long.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Long>) deserializedDataObject).put(key, (Long) value.get(key));
				}
			} else if ((Float.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Float>) deserializedDataObject).put(key, (Float) value.get(key));
				}
			} else if ((Double.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Double>) deserializedDataObject).put(key, (Double) value.get(key));
				}
			} else if ((String.class).equals(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, String>) deserializedDataObject).put(key, (String) value.get(key));
				}
			} else if (isTransportable(genericValueClass)) {
				while (keys.hasNext()) {
					String key = keys.next();
					((HashMap<String, Transportable>) deserializedDataObject).put(key, (Transportable) readTransportable(value.get(key)));
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected byte[] stringify(Object serilizedData) throws TransportException {
		return (serilizedData.toString()).getBytes();
	}

	/*
	 * @Override public byte[] tranportMap(Map<String, Transportable>
	 * mergedModel) throws TransportException { JSONObject obj = new
	 * JSONObject(); try { Iterator<String> keyIterator =
	 * (mergedModel.keySet()).iterator(); while (keyIterator.hasNext()) {
	 * 
	 * String key = keyIterator.next(); obj.put(key, new JSONObject(new
	 * String(serialize(mergedModel.get(key))))); } } catch (Exception e) { if
	 * (e instanceof TransportException) { throw (TransportException)e; } else {
	 * throw new TransportException(e); } } return (obj.toString()).getBytes();
	 * }
	 */
}
